using System;
using System.Collections.Generic;
using System.Data;
using PCSComUtils.Common;
using PCSComProduction.WorkOrder.DS;
using PCSComUtils.DataContext;
using System.Transactions;
using PCSComUtils.DataAccess;
using System.Linq;
using log4net;

namespace PCSComProduction.WorkOrder.BO
{
	public class ReleaseWorkOrderBO
	{
	    private readonly ILog _logger = LogManager.GetLogger(typeof (ReleaseWorkOrderBO));
		
        /// <summary>
        ///     Searches for the first un release wo.
        /// </summary>
        /// <param name="pintCcnid">
        ///     The pint ccnid.
        /// </param>
        /// <param name="pintMasLocId">
        ///     Identifier for the pint mas location.
        /// </param>
        /// <param name="pstrWONo">
        ///     The pstr wo no.
        /// </param>
        /// <param name="pintProLineId">
        ///     Identifier for the pint pro line.
        /// </param>
        /// <param name="pintSaleOrderDetailId">
        ///     Identifier for the pint sale order detail.
        /// </param>
        /// <param name="pdtmFromStartDate">
        ///     Date of the pdtm from start.
        /// </param>
        /// <param name="pdtmToStartDate">
        ///     Date of the pdtm to start.
        /// </param>
        /// <param name="pintStatus">
        ///     The pint status.
        /// </param>
        /// <returns>
        ///     The found un release wo.
        /// </returns>
		public DataSet SearchUnReleaseWO(int pintCcnid, int pintMasLocId, string pstrWONo, int pintProLineId, int pintSaleOrderDetailId, DateTime pdtmFromStartDate, DateTime pdtmToStartDate, int pintStatus)
		{
			var dsWODetail = new PRO_WorkOrderDetailDS();
			return dsWODetail.SearchUnReleaseWO(pintCcnid , pintMasLocId , pstrWONo , pintProLineId, pintSaleOrderDetailId, pdtmFromStartDate , pdtmToStartDate, pintStatus);
		}
		
        /// <summary>
        ///     Approve work order.
        /// </summary>
        /// <param name="data">
        ///     The data.
        /// </param>
        /// <param name="releasing">
        ///     true to releasing.
        /// </param>
        public void ApproveWorkOrder(DataSet data, bool releasing)
        {
            using (var trans = new TransactionScope())
            {
                try
                {
                    using (var db = new PCSDataContext(Utils.Instance.ConnectionString))
                    {
                        foreach (DataRow row in data.Tables[0].Rows)
                        {
                            #region ignore all un-check rows

                            bool selected;
                            try
                            {
                                selected = Convert.ToBoolean(row["Selected"]);
                            }
                            catch (Exception)
                            {
                                selected = false;
                            }
                            if (!selected)
                            {
                                continue;
                            }

                            #endregion

                            var workOrderDetail = db.PRO_WorkOrderDetails.SingleOrDefault(e => e.WorkOrderDetailID == Convert.ToInt32(row[PRO_WorkOrderDetailTable.WORKORDERDETAILID_FLD]));
                            if (workOrderDetail == null)
                            {
                                continue;
                            }

                            if (releasing)
                            {
                                workOrderDetail.UserID = SystemProperty.UserID;
                                workOrderDetail.Status = (int)WOLineStatus.Released;
                            }
                            else
                            {
                                workOrderDetail.UserID = null;
                                workOrderDetail.Status = (int)WOLineStatus.Unreleased;
                            }
                        }
                        db.SubmitChanges();
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                    throw;
                }

                trans.Complete();
            }
        }
		public DataTable GetUncompletedQuantity()
		{
			var dsDetail = new PRO_WorkOrderDetailDS();
			return dsDetail.GetUncompletedQuantity();
		}
		public DataSet GetBOMOfLines(string workOrderDetailId)
		{
			var dsWobom = new PRO_WOBOMDS();
			return dsWobom.ListComponentByWODetail(workOrderDetailId);
		}

        /// <summary>
        ///     Query if list of 'workOrderDetailId' is unreleaseable.
        /// </summary>
        /// <param name="workOrderDetailId">
        ///     Identifier for the work order detail.
        /// </param>
        /// <param name="saleOrderDetailId">
        ///     Identifier for the sale order detail.
        /// </param>
        /// <returns>
        ///     true if unreleaseable, false if not.
        /// </returns>
		public bool IsUnreleaseable(List<int> workOrderDetailId, List<int> saleOrderDetailId)
		{
            using (var dataContext = new PCSDataContext(Utils.Instance.ConnectionString))
            {
                // PRO_IssueSubMaterialMaster
                var used = dataContext.PRO_IssueSubMaterialMasters.Any(i => saleOrderDetailId.Contains(i.SaleOrderDetailID));
                if (used)
                {
                    return false;
                }
                // PRO_IssueMaterialDetail
                used = dataContext.PRO_IssueMaterialDetails.Any(i => i.WorkOrderDetailID != null && workOrderDetailId.Contains((int) i.WorkOrderDetailID));
                if (used)
                {
                    return false;
                }
                // PRO_WorkOrderCompletion
                used = dataContext.PRO_WorkOrderCompletions.Any(i => workOrderDetailId.Contains(i.WorkOrderDetailID));
                if (used)
                {
                    return false;
                }
                // PRO_RequiredMaterialDetail
                used = dataContext.PRO_RequiredMaterialDetails.Any(i => workOrderDetailId.Contains(i.WorkOrderDetailID));
                if (used)
                {
                    return false;
                }
            }
            return true;
		}
	}
}
